#include "../include/Camera.h"
#include <math.h>

Camera::Camera()
{
    //ctor
}

/**
* Comstructeur de la camera contenant la grille de rendu
* @param position position de l'oeil de la camera
* @param direction direction de la camera
* @param focale focale de la camera (distance oeil-grille)
* @param image image de rendu
* @return une camera
*/
Camera::Camera(pVect position, pVect direction, float focale, Image* image){
    direction.normalize();
    this->position = position;
    this->direction = direction;
    this->focale = focale;
    this->image = image;

    //determiner la taille d'un pixel
    this->taillePixelX = 36.0/(float)image->width;
    this->taillePixelY = 24.0/(float)image->height;

    //coordonnées du premier pixel en haut a gauche de la grille
    this->coordPremierPixelX = -18 + (this->taillePixelX/2.0);
    this->coordPremierPixelY = this->focale;
    this->coordPremierPixelZ = 12 - (this->taillePixelY/2.0);

    //calcul des autres termes du repère de la camera
    this->vA = direction^pVect(0,0,1);
    this->vC = this->vA^direction;
}

Camera::~Camera()
{
    //dtor
}

/**
* Methode permettant la création d'un rayon oeil-pixel
* @param i coordonée d'abscisse d'un pixel dans la grille
* @param j coordonnée d'ordonnée d'un pixek dans la grille
* @return un rayon (oeil-pixel)
*/
pVect Camera::creerRayon(int i, int j){
    //calcul des coordonnées du centre du pixel demandé
    float centrePixelX = this->coordPremierPixelX + (i*this->taillePixelX);
    float centrePixelZ = this->coordPremierPixelZ - (j*this->taillePixelY);
    //coordonnée du rayon oeil-pixel relatif au repère de la camera
    pVect rayRelatif(centrePixelX, this->coordPremierPixelY, centrePixelZ);

    //coordonnée du rayon oeil-pixel relatif au repère général
    pVect rayon((vA.x*rayRelatif.x + direction.x*rayRelatif.y + vC.x*rayRelatif.z),(vA.y*rayRelatif.x + direction.y*rayRelatif.y + vC.y*rayRelatif.z),(vA.z*rayRelatif.x + direction.z*rayRelatif.y + vC.z*rayRelatif.z));
    rayon.normalize();
    return rayon;
}

/**
* Methode permettant la création de plusieurs rayons oeil-pixel dans l'optique de l'anti-aliasing
* @param i coordonée d'abscisse d'un pixel dans la grille
* @param j coordonnée d'ordonnée d'un pixek dans la grille
* @param ordreAA nombre de rayon = 4^ordreAA tirer dans un pixel (nombre de subdivision)
* @return un tableau de rayon (oeil-pixel)
*/
pVect* Camera::creerRayonAntiAliasing(int i, int j, int ordreAA){
    int nbrRayon = pow(4,ordreAA);
    int nbPixLarg = pow(2,ordreAA);
    pVect* ptTabRay = new pVect [nbrRayon];

    //calcul de la taille d'une subdivision de pixel
    float tailleMiniPixX = this->taillePixelX / nbPixLarg;
    float tailleMiniPixY =  this->taillePixelY / nbPixLarg;
    //calcul du coin superieur gauche d'une subdivision de pixel
    float coinX = -18 + (i*this->taillePixelX)+tailleMiniPixX;
    float coinY = this->focale;
    float coinZ = 12 - (j*this->taillePixelY)-tailleMiniPixY;

    //pour chaque subdivision de pixel
    for(int u = 0; u<nbPixLarg; u++){
        for(int h = 0; h<nbPixLarg; h++){
            //calcul du centre de la subdivision
            float centreMiniPixX = coinX + (u*tailleMiniPixX);
            float centreMiniPixZ = coinZ - (h*tailleMiniPixY);
            //calcul du rayon oeil-pixel relatif au repère de la camera
            pVect rayRelatif(centreMiniPixX, coinY, centreMiniPixZ);
            //coordonnée du rayon oeil-pixel relatif au repère général
            pVect rayon((vA.x*rayRelatif.x + direction.x*rayRelatif.y + vC.x*rayRelatif.z),(vA.y*rayRelatif.x + direction.y*rayRelatif.y + vC.y*rayRelatif.z),(vA.z*rayRelatif.x + direction.z*rayRelatif.y + vC.z*rayRelatif.z));
            rayon.normalize();

            //remplissage du tableau à retourner
            ptTabRay[u+nbPixLarg*h].x = rayon.x;
            ptTabRay[u+nbPixLarg*h].y = rayon.y;
            ptTabRay[u+nbPixLarg*h].z = rayon.z;
        }
    }
    return ptTabRay;
}
